package cn.iocoder.yudao.adminserver.franky.LRU;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description:
 * @Author: franky
 * @CreateDate: 2021/4/15 1:15 下午
 * @Version: 1.0
 */
public class LRUNode2 {

    private int capacity;
    Map<String, Node2> lruMap;
    private Node2 head;
    private Node2 end;


    public LRUNode2(Integer capacity) {
        this.capacity = capacity;
        lruMap = new ConcurrentHashMap();
    }

    public Node2 get(String key) {
        if (!lruMap.containsKey(key)) {
            return null;
        }
        Node2 node2 = lruMap.get(key);
        refreshNode(node2);
        return node2;
    }

    public void add(String key, String value) {
        Node2 node = lruMap.get(key);
        if (null == node) {
            // 判断是否内存满了
            if (lruMap.size() >= capacity) {
                String oldKey = removeNode(head);
                lruMap.remove(oldKey);
            }
            node = new Node2(key, value);
            addNode(node);
            lruMap.put(key, node);
        } else {
            node.value = value;
            refreshNode(node);
        }
    }

    public void remove(String key) {
        if (!lruMap.containsKey(key)) {
            return;
        }
        Node2 node2 = lruMap.get(key);
        lruMap.remove(key);
        removeNode(node2);
    }

    public void refreshNode(Node2 node2) {
        if (end == node2) {
            return;
        }
        // 移除节点
        removeNode(node2);
        // 重新插入节点
        addNode(node2);
    }

    private void addNode(Node2 node) {
        if (end != null) {
            // 注意这里的逻辑理解下
            end.next = node;
            node.pre = end;
            node.next = null;
        }
        end = node;
        if (null == head) {
            head = node;
        }
    }

    private String removeNode(Node2 node2) {
        // 如果是单节点
        if (head == node2 && end == node2) {
            head = null;
            end = null;
        } else if (head == node2) {
            // 头部节点
            head = head.next;
            head.pre = null;
        } else if (end == node2) {
            //尾部节点
            end = end.pre;
            end.next = null;
        } else {
            //中间节点
            node2.next.pre = node2.pre;
            node2.pre.next = node2.next;
        }
        return node2.key;
    }

    private class Node2 {
        private String key;
        private String value;
        private Node2 pre;
        private Node2 next;

        public Node2(String key, String value) {
            this.key = key;
            this.value = value;
            this.pre = null;
            this.next = null;
        }

    }

}
